<?php
namespace cms\modules\backend\controllers;

use Yii;
use yii\db\Expression;
use cms\controllers\AuthController;
use app\models\CoreConfig;
use app\models\ContentCategory;
use app\models\Content;
use app\models\ContentSearch;
use app\models\ContentAttrRelationships;
use app\models\Tags;
use app\models\TagsRelationships;
use common\component\exception\ErrMap;
use common\component\tool\Tool;
use common\models\OperationLog;
use common\behaviors\Sort;
use yii\helpers\Html;


class ContentController extends AuthController
{
    public function behaviors()
    {
        return [
             // 注册匿名行为，只有行为类名
            Sort::className(),

        ];
    }

    /*内容列表*/
    public function actionContentList()
    {
        if(!isset($this->get['catid'])){
            $count = 0;
            $pageSize = Tool::getPageSize();
            $currPage = 1;
            $contentList = array();
            $coreConfig = [];
        }else{
            if(isset($this->get['page'])){
                $currPage = intval($this->get['page']?$this->get['page']:1);
            }else{
                $currPage = 1;
            }
            $pageSize = Tool::getPageSize();
            $this->get['app_id'] = $this->app_id;
            // P($this->get);
            $search = (new ContentSearch())->search($this->get);
            if($search === false){//验证搜索参数不通过
                $count = 0;
                $contentList = array();
                $coreConfig = [];
            }else{
                $count = $search
                /*注释原因：后台只需要取出 直属栏目的内容*/
                // ->andWhere(new Expression("FIND_IN_SET(:catid, catids)", [":catid"=>$this->get['catid']]))
                ->count();
                $contentList = $search->select(['content_id', 'title', 'flag', 'state', 'rejected_reason', 'member_view', 'display', 'istop', 'pc_preview_count', 'mobile_preview_count', 'add_time'])
                              /*注释原因：后台只需要取出 直属栏目的内容*/
                              // ->andWhere(new Expression("FIND_IN_SET(:catid, catids)", [":catid"=>$this->get['catid']]))
                              ->offset($pageSize*($currPage-1))->limit($pageSize)
                              ->orderBy([
                                    'istop' => SORT_DESC,
                                    'toptime' => SORT_DESC,
                                    'sort' => SORT_DESC,
                                    'add_time' => SORT_DESC
                                ])
                              // ->createCommand()->getRawSql();
                              ->asArray()->all();
                /*取出域名，为了后台能够直接预览内容*/
                $coreConfig = CoreConfig::find()->select(['pc_url', 'mobile_url'])
                               ->where('app_id = :id', [':id' => $this->app_id])
                               ->asArray()->one();

            }
        }
        // P($contentList);
        $res = array(
            'list' => $contentList,
            'url' => $coreConfig,
            'pageInfo' => array(
                'count' => intval($count),
                'currPage' => $currPage,
                'pageSize' => $pageSize,
            ),
        );
        return Tool::showRes([0, '获取成功'], $res);
    }

    /*添加内容*/
    public function actionAddContent()
    {
        if(Yii::$app->request->isPost){
            // P($this->post);
            /*如果是state值为3的话，说明是 添加并审核，此时必须先认证下是否有审核权限，没有的话直接返回*/
            if( (isset($this->post['Content']['state'])) 
                and ($this->post['Content']['state'] == 3) 
                and !$this->hasAuditAuth() ){
                $backInfo = ErrMap::getError(10020);//返回信息
            }else{
                $content = new Content;
                $transaction = Yii::$app->db->beginTransaction();//事物处理
                $pass = true;
                try{
                    /*1、添加内容*/
                    if(!$content_id = $content->addContent($this->post, $this->app_id)){
                        $pass = false;
                        if($content->hasErrors()){
                            $backInfo = ErrMap::getError(10005);//返回信息
                            $exception = $content->getErrors();//异常信息
                        }else{
                            throw new \Exception('添加内容失败');
                        }
                    }
                    /*2、添加字段值 与 自定义字段的关联*/
                    if($pass and isset($this->post['ContentAttrValue']) 
                        and is_array($this->post['ContentAttrValue']) 
                        and count($this->post['ContentAttrValue'])>0){
                        if(($res = $this->addContentAttrRelationships($this->post['ContentAttrValue'], $content_id)) !== true){
                            $pass = false;
                            if(gettype($res) == 'array'){
                                $exception = $res;
                            }else{
                                throw new \Exception($res);
                            }
                        }
                    }
                    /*3、添加Tag标签*/
                    if($pass){
                        if(($res = $this->addTags($content_id)) !== true){
                            $pass = false;
                            if(gettype($res) == 'array'){
                                $exception = $res;
                            }else{
                                throw new \Exception($res);
                            }
                        }
                    }
                    /*4.增加此分类的内容数量， 其他分类不增加*/
                    ContentCategory::updateAllCounters(['content_count' => 1], 'catid = :id', [':id' => $this->post['Content']['catids'][0]['catid']]);

                    if($pass){
                        $backInfo = [0, '添加内容成功'];//返回信息
                        $transaction->commit();
                    }
                }catch(\Exception $exception){
                    $transaction->rollback();       
                };
            }


        };

        if(!isset($backInfo)){
            $backInfo = ErrMap::getError(10005);//返回信息
        }
        if(!isset($exception)){
            $exception = '';//异常信息
        }
        //操作日志
        if(gettype( $res = OperationLog::addLog(Tool::operationLogArgs($backInfo, $this->userInfo), $exception) ) != 'boolean'){
            return $res;
        };
    }


    /*修改内容*/
    public function actionModifyContent()
    {
        /*取出单个数据*/
        if(Yii::$app->request->isGet){
            // P($this->get);
            $catid = isset($this->get['catid'])?$this->get['catid']:'';
            $content_id = isset($this->get['id'])?$this->get['id']:'';
            if($catid or $content_id){
                if($content_id){
                    $content = Content::find()
                            ->select(['content_id', 'catids', 'title', 'titlecolor', 'flag', 'preview', 'istop', 'outside', 'url_target', 'outside_url', 'source', 'author', 'keyword', 'describe', 'content', 'state', 'member_view', 'previewtime', 'integral', 'display', 'add_time'])
                            ->where('content_id = :cid', [':cid' => $content_id])
                            ->asArray()->one();
                }else{//说明是单页,获取次栏目最大的ID数据
                    $content = Content::find()
                            ->select(['content_id', 'catids', 'title', 'titlecolor', 'flag', 'preview', 'istop', 'outside', 'url_target', 'outside_url', 'source', 'author', 'keyword', 'describe', 'content', 'state', 'member_view', 'previewtime', 'integral', 'display', 'add_time'])
                            ->where('catids = :cid', [':cid' => $catid])
                            ->orderBy(['content_id' => SORT_DESC])
                            ->asArray()->one();
                    $content_id = $content['content_id'];
                    // P($content_id);
                }
                // P($content);
                if(!is_null($content)){
                    if(!empty($content['flag'])){
                        $content['flag'] = explode(',', $content['flag']);
                    }else{
                        $content['flag'] = [];
                    }
                    if(!empty($content['preview'])){
                        $content['preview'] = explode(',', $content['preview']);
                    }else{
                        $content['preview'] = [];
                    }
                    if(!empty($content['content'])){
                        $content['content'] = Html::decode($content['content']);
                    }

                    /*获取标签*/
                    $tagsRelationships = TagsRelationships::find()
                                ->select('unionid, {{%tags_relationships}}.tid')
                                ->joinWith('tag')
                                ->where('{{%tags_relationships}}.app_id = :app_id and unionid = :unionid', [':app_id' => $this->app_id, ':unionid' => $content_id])
                                // ->createCommand()->getRawSql();
                                ->asArray()->all();
                    // echo $this->app_id . '-' .  $content_id;
                    // P($tagsRelationships);

                    /*获取自定义字段*/
                    $contentAttrRelationships = ContentAttrRelationships::find()
                                ->select('content_id, {{%content_attr_relationships}}.attr_id, {{%content_attr_relationships}}.attr_value')
                                ->joinWith('attrName')
                                ->where('{{%content_attr_relationships}}.app_id = :app_id and content_id = :id', [':app_id' => $this->app_id, ':id' => $content_id])
                                ->asArray()->all();
                    foreach($contentAttrRelationships as $k => $v){
                        /*多选的，需要转成数组*/
                        if($v['attrName']['attr_type'] == 4 or $v['attrName']['attr_type'] == 7){
                            $contentAttrRelationships[$k]['attr_value'] = json_decode($v['attr_value']);
                        }
                        /*编辑器，需要转义*/
                        if($v['attrName']['attr_type'] == 6){
                            $contentAttrRelationships[$k]['attr_value'] = Html::decode($contentAttrRelationships[$k]['attr_value']);
                        }
                    }
                    // P($contentAttrRelationships);

                    $data = array(
                        'content' => $content,
                        'tags' => $tagsRelationships,
                        'attr' => $contentAttrRelationships
                    );

                    return Tool::showRes([0, '获取成功'], $data);
                }else{
                    $data = array(
                        'content' => '',
                        'tags' => '',
                        'attr' => ''
                    );
                    return Tool::showRes([0, '获取成功'], $data);
                };
            }
        }


        /*如果有数据，进行修改*/
        if(Yii::$app->request->isPost){
            // P($this->post);
            $content_id = isset($this->post['Content']['id'])?intval($this->post['Content']['id']):'';
            if(!$content_id){
                $backInfo = ErrMap::getError(10005);//返回信息
            }else{
                $transaction = Yii::$app->db->beginTransaction();//事物处理
                $pass = true;
                try{

                    /*修改内容信息*/
                    $content = new Content;
                    if(!$content->modifyContent($this->post, $content_id)){
                        $pass = false;
                        if($content->hasErrors()){
                            $backInfo = ErrMap::getError(10005);//返回信息
                            $exception = $content->getErrors();//异常信息
                        }else{
                            throw new \Exception('修改内容失败');
                        }
                    }
                    /*如果是挪动栏目，需要把就栏目的数据总数减一，新栏目加一*/
                    if(isset($this->post['Content']['mark']) and 
                        $this->post['Content']['mark'] == 'setCategory' and
                        ($this->post['Content']['oldcatid'] != $this->post['Content']['catids'][0]['catid'])){
                        /*老栏目减一*/
                        ContentCategory::updateAllCounters(['content_count' => -1], 'catid = :catid', [':catid' => $this->post['Content']['oldcatid']]);
                        /*新栏目加一*/
                        ContentCategory::updateAllCounters(['content_count' => 1], 'catid = :catid', [':catid' => $this->post['Content']['catids'][0]['catid']]);
                    }

                    if(!isset($this->post['Content']['mark'])){//如果纯修改，不是光设置显示状态、置顶等操作
                        /*2、添加字段值 与 自定义字段的关联*/
                        ContentAttrRelationships::deleteAll('content_id = :id', [':id' => $content_id]);//先删除之前所有的关联标签
                        if($pass and isset($this->post['ContentAttrValue']) 
                            and is_array($this->post['ContentAttrValue']) 
                            and count($this->post['ContentAttrValue'])>0){
                            if(($res = $this->addContentAttrRelationships($this->post['ContentAttrValue'], $content_id)) !== true){
                                $pass = false;
                                if(gettype($res) == 'array'){
                                    $exception = $res;
                                }else{
                                    throw new \Exception($res);
                                }
                            }
                        }
                        /*3、添加Tag标签*/
                        TagsRelationships::deleteAll('unionid = :id and flag = 2', [':id' => $content_id]);//先删除之前所有的关联标签
                        if($pass){
                            if(($res = $this->addTags($content_id)) !== true){
                                $pass = false;
                                if(gettype($res) == 'array'){
                                    $exception = $res;
                                }else{
                                    throw new \Exception($res);
                                }
                            }
                        }
                    }


                    if($pass){
                        $backInfo = [0, '修改内容成功'];//返回信息
                        $transaction->commit();
                    }

                }catch(\Exception $exception){
                    $transaction->rollback();       
                };   
            }

            if(!isset($backInfo)){
                $backInfo = ErrMap::getError(10005);//返回信息
            }
            if(!isset($exception)){
                $exception = '';//异常信息
            }
            //操作日志
            if(gettype( $res = OperationLog::addLog(Tool::operationLogArgs($backInfo, $this->userInfo), $exception) ) != 'boolean'){
                return $res;
            };
        }

        return Tool::showRes(ErrMap::getError(10005));
    }


    /*审核*/
    public function actionAuditContent()
    {
        /*如果有数据，进行修改*/
        if(Yii::$app->request->isPost){
            // P($this->post);
            $content_id = isset($this->post['Content']['id'])?intval($this->post['Content']['id']):'';
            if($content_id){
                $content = Content::find()->select('state')
                            ->where('content_id = :id', [':id' => $content_id])->one();
                if($content->state != 2){//如果是审核的话，只有待提交的状态才能审核
                    $backInfo = ErrMap::getError(20001);//返回信息
                }else{
                    $content = new Content;
                    if($content->modifyContent($this->post, $content_id)){
                        $backInfo = [0, '审核内容操作成功'];//返回信息
                    }else{
                        if($content->hasErrors()){
                            $backInfo = ErrMap::getError(10005);//返回信息
                            $exception = $content->getErrors();//异常信息
                        }else{
                            throw new \Exception('审核内容失败');
                        }
                    }
                }

                if(!isset($backInfo)){
                    $backInfo = ErrMap::getError(10005);//返回信息
                }
                if(!isset($exception)){
                    $exception = '';//异常信息
                }
                //操作日志
                if(gettype( $res = OperationLog::addLog(Tool::operationLogArgs($backInfo, $this->userInfo), $exception) ) != 'boolean'){
                    return $res;
                };
            }
        }
        return Tool::showRes(ErrMap::getError(10005));
    }

    /*设置状态*/
    public function actionSetContentState()
    {
        $id = isset($this->post['id'])?$this->post['id']:'';
        $flag = isset($this->post['flag'])?$this->post['flag']:'';
        $type = gettype($id);
        if($id and ($type == 'string' or $type == 'array') and in_array($flag, [1,2,3,5])) {
            $content = new Content;
            if($type == 'string'){//单个
                if($content->updateAll(['state' => $flag], 'content_id = :id', [':id' => $id])){//成功
                    $backInfo = [0, '更改内容状态成功'];//返回信息
                }else{//失败
                    $backInfo = ErrMap::getError(10013, '更改内容状态失败');//返回信息
                }
            }
            if($type == 'array'){//批量
                if($content->updateAll(['state' => $flag], ['in', 'content_id', $id])){//成功
                    $backInfo = [0, '更改内容状态成功'];//返回信息
                }else{//失败
                    $backInfo = ErrMap::getError(10013, '更改内容状态失败');//返回信息
                }
            }

            if(!isset($exception)){
                $exception = '';//异常信息
            }

            //操作日志
            if(gettype( $res = OperationLog::addLog(Tool::operationLogArgs($backInfo, $this->userInfo), $exception) ) != 'boolean'){
                return $res;
            };
        }

        return Tool::showRes(ErrMap::getError(10005));
    }

    /*删除内容*/
    public function actionDeleteContent()
    {
        $id = isset($this->post['id'])?$this->post['id']:'';
        $type = gettype($id);
        if($id and ($type == 'string' or $type == 'array')){
            $transaction = Yii::$app->db->beginTransaction();//事物处理
            $pass = true;
            try{
                if($type == 'string'){//单个删除
                    $content = Content::find()->where('content_id = :id', [':id' => $id])->one();
                    if(!is_null($content)){
                        /*删除内容*/
                        if(!$content->delete()){
                            $backInfo = ErrMap::getError(10013, '删除内容失败');//返回信息
                            $pass = false;
                        }
                        /*先删除之前所有的关联属性*/
                        if($pass){
                            ContentAttrRelationships::deleteAll('content_id = :id', [':id' => $id]);
                        }
                        /*先删除之前所有的关联标签*/
                        if($pass){
                            TagsRelationships::deleteAll('unionid = :id and flag = 2', [':id' => $id]);
                        }
                        /*减少此分类的内容数量， 其他分类不减少*/
                        if($pass){
                            $tmp = explode(',', $content->catids);
                            if($pass and !ContentCategory::updateAllCounters(['content_count' => -1], 'catid = :id', [':id' => $tmp[0]])){
                                $backInfo = ErrMap::getError(10013, '删除内容失败');//返回信息
                                $pass = false;
                            }
                        }
                    }
                }
                if($type == 'array'){//批量删除
                    foreach($id as $k => $v){
                        $content = Content::find()->where('content_id = :id', [':id' => $v])->one();
                        if(!is_null($content)){
                            /*删除内容*/
                            if(!$content->delete()){
                                $backInfo = ErrMap::getError(10013, '删除内容失败');//返回信息
                                $pass = false;
                            }
                            /*减少此分类的内容数量， 其他分类不减少*/
                            $tmp = explode(',', $content->catids);
                            if($pass){
                                ContentCategory::updateAllCounters(['content_count' => -1], 'catid = :id', [':id' => $tmp[0]]);
                                /*先删除之前所有的关联属性*/
                                ContentAttrRelationships::deleteAll('content_id = :id', [':id' => $v]);
                                /*先删除之前所有的关联标签*/
                                TagsRelationships::deleteAll('unionid = :id and flag = 2', [':id' => $v]);
                            }
                        }
                    }
                }

                if($pass){
                    $backInfo = [0, '删除内容成功'];//返回信息
                    $transaction->commit();
                }
            }catch(\Exception $exception){
                $transaction->rollback();       
            };

            if(!isset($backInfo)){
                $backInfo = ErrMap::getError(10005);//返回信息
            }
            if(!isset($exception)){
                $exception = '';//异常信息
            }
            //操作日志
            if(gettype( $res = OperationLog::addLog(Tool::operationLogArgs($backInfo, $this->userInfo), $exception) ) != 'boolean'){
                return $res;
            };

        }
        return Tool::showRes(ErrMap::getError(10005));
    }

    /*排序*/
    public function actionSetSort()
    {
        if(Yii::$app->request->isPost){
            $sort = $this->post['sort'];
            // P($sort);
            if(!empty($sort) and is_array($sort)){
                if($this->setSortList(new Content, $sort)){
                    $backInfo = [0, '设置内容排序成功'];//返回信息
                }

            }
            if(!isset($backInfo)){
                $backInfo = ErrMap::getError(10005);//返回信息
            }
            if(!isset($exception)){
                $exception = '';//异常信息
            }
            //操作日志
            if(gettype( $res = OperationLog::addLog(Tool::operationLogArgs($backInfo, $this->userInfo), $exception) ) != 'boolean'){
                return $res;
            };
        }
        return Tool::showRes(ErrMap::getError(10005));
    }


    /*添加 内容 与 自定义字段的关系*/
    private function addContentAttrRelationships($data, $content_id)
    {
        // P($data);
        $pass = true;
        foreach($data as $k => $v){
            $contentAttrRelationships = new ContentAttrRelationships;
            $v['app_id'] = $this->app_id;
            $v['content_id'] = $content_id;
            if(isset($v['default']) and is_array($v['default'])){
                // $v['attr_value'] = implode(',', $v['default']);
                $v['attr_value'] = json_encode($v['default']);
            }else{
                $v['attr_value'] = isset($v['default'])?$v['default']:'';
            }
            if(isset($v['attr_type']) and $v['attr_type'] == 6){
                $v['attr_value'] = Html::encode($v['attr_value']);
            }
            if(!$contentAttrRelationships->addRelationships($v)){
                $pass = false;
                if($contentAttrRelationships->hasErrors()){
                    $backInfo = ErrMap::getError(10005);//返回信息
                    $exception = $contentAttrRelationships->getErrors();//异常信息
                }else{
                    $exception = '添加内容与自定义字段失败';
                }
                break;
            }
        }
        if($pass){
            return true;
        }else{
            return $exception;
        }
    }

    /*增加标签 和 关联标签 仅限本控制器使用*/
    private function addTags($unionid, $flag = 2)
    {
        $pass = true;
        /*增加tag标签*/
        $updataTags = [];//需要增加热度的标签ID
        if(isset($this->post['Tags']) and gettype($this->post['Tags']) == 'array'){
            foreach($this->post['Tags'] as $k => $v){
                if(empty($v['tid'])){
                    $tags = new Tags;
                    $data = array(
                        'Tags' => $v
                    );
                    $data['Tags']['heat'] = 1;
                    if( ($tid = $tags->addTag($data, $this->app_id, true)) > 0 ){
                        array_push($updataTags, $tid);
                    }else{
                        $pass = false;
                        if($tags->hasErrors()){
                            $backInfo = ErrMap::getError(10005);//返回信息
                            $exception = $tags->getErrors();//异常信息
                        }else{
                            $exception = '添加标签异常失败';
                        }
                        break;
                    }
                }else{
                    array_push($updataTags, $v['tid']);
                    Tags::updateAllCounters(['heat' => 1], 'tid = :tid', [':tid' => $v['tid']]);
                }
            };
        }

        /*添加标签关联*/
        // P($updataTags);
        if($pass){
            foreach($updataTags as $k => $v){
                $tagsRelationships = new TagsRelationships;
                $data = array(
                    'TagsRelationships' => array(
                        'unionid' => $unionid,
                        'tid' => $v,
                        'flag' => $flag
                    )
                );
                if(!$tagsRelationships->addRelationships($data, $this->app_id)){
                    $pass = false;
                    if($tagsRelationships->hasErrors()){
                        $backInfo = ErrMap::getError(10005);//返回信息
                        $exception = $tagsRelationships->getErrors();//异常信息
                    }else{
                        $exception = '添加标签关联失败';
                    }
                    break;
                }
            }
        }

        if($pass){
            return true;
        }else{
            return $exception;
        }

    }


    /*判读是否有 审核权限*/
    private function hasAuditAuth()
    {
        /*此处写个伪代码，待开发完RBAC后再完善*/
        return true;
    }


}
